package xyz.mumuwei.youthcourseserver.exception;

import com.alipay.api.AlipayApiException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.exceptions.TemplateInputException;
import org.thymeleaf.exceptions.TemplateProcessingException;
import xyz.mumuwei.youthcourseserver.common.lang.Const;
import xyz.mumuwei.youthcourseserver.common.lang.Result;

import javax.mail.MessagingException;
import javax.validation.ConstraintViolationException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;

/**
 * 全局异常处理类
 * @author mumuwei
 * @date 2022/2/19
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(BizException.class)
    public Result bizExceptionHandler(BizException e){
        log.error("业务处理异常！原因为:-->{}", e.getMessage());
        return Result.fail(Integer.parseInt(e.getErrorCode()), e.getErrorMsg());
    }

    @ResponseBody
    @ExceptionHandler(CommonException.class)
    public Result bizExceptionHandler(CommonException e){
        log.error("业务处理异常！原因为:-->{}", e.getMessage());
        return Result.fail(500, e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(NullPointerException.class)
    public Result exceptionHandler(NullPointerException e){
        log.error("发生空指针异常！！原因为:-->{}", e.getMessage());
        e.printStackTrace();
        return Result.fail(400, "请求的数据格式不符！");
    }

    @ResponseBody
    @ExceptionHandler(IllegalArgumentException.class)
    public Result exceptionHandler(IllegalArgumentException e){
        log.error("参数为空异常！原因为:-->{}", e.getMessage());
        return Result.fail(400, "请求的携带参数有误！");
    }


    @ResponseBody
    @ExceptionHandler(MissingPathVariableException.class)
    public Result exceptionHandler(MissingPathVariableException e){
        log.error("URL模板id参数异常！原因为:-->{}", e.getMessage());
        return Result.fail(400, "请求的携带参数有误！");
    }
    @ResponseBody
    @ExceptionHandler(TokenExpiredException.class)
    public Result exceptionHandler(TokenExpiredException e){
        log.error("token过期！原因为:-->{}", e.getMessage());
        return Result.fail(Const.EXPIRED_TOKEN_CODE, Const.EXPIRED_TOKEN_MSG);
    }

    @ResponseBody
    @ExceptionHandler(JWTVerificationException.class)
    public Result exceptionHandler(JWTVerificationException e){
        log.error("token校验未通过，发生异常！原因为:-->{}", e.getMessage());
        return Result.fail(Const.ILLEGAL_TOKEN_CODE, Const.ILLEGAL_TOKEN_MSG);
    }

    @ResponseBody
    @ExceptionHandler(IOException.class)
    public Result exceptionHandler(IOException e){
        log.error("IO操作引发异常！原因为:-->{}", e.getMessage());
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(NoSuchAlgorithmException.class)
    public Result exceptionHandler(NoSuchAlgorithmException e){
        log.error("请求特定加密算法但在环境中不可用时，引发异常！原因为:-->{}", e.getMessage());
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(FileNotFoundException.class)
    public Result exceptionHandler(FileNotFoundException e){
        log.error("找不到文件引发异常！原因为:-->{}", e.getMessage());
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public Result exceptionHandler(BindException e){
        String message = e.getBindingResult().getAllErrors().stream().findFirst().get().getDefaultMessage();
        log.error("参数校验异常！原因为:-->{}", message);
        return Result.fail(400, message);
    }

    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public Result exceptionHandler(ConstraintViolationException  e){
        String message = e.getMessage().split(":")[1];
        log.error("单个参数校验异常！原因为:-->{}", e.getMessage());
        return Result.fail(400, message);
    }

    @ResponseBody
    @ExceptionHandler(AssertionError.class)
    public Result exceptionHandler(AssertionError  e){
        log.error("AssertionError！原因为:-->{}", e.getMessage());
        return Result.fail(400, e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(AlipayApiException.class)
    public Result exceptionHandler(AlipayApiException  e){
        log.error("AlipayApiException！原因为:-->{}", e.getMessage());
        return Result.fail(500, "请求支付宝支付出现错误！");
    }

    @ResponseBody
    @ExceptionHandler(ParseException.class)
    public void exceptionHandler(ParseException  e){
        log.error("ParseException！原因为:-->{}", e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(UnsupportedEncodingException.class)
    public Result exceptionHandler(UnsupportedEncodingException e){
        log.error("不支持编码异常。UnsupportedEncodingException！原因为:-->{}", e.getMessage());
        return Result.fail(500, "服务器内部错误!");
    }

    @ResponseBody
    @ExceptionHandler(SchedulerException.class)
    public Result exceptionHandler(SchedulerException e){
        log.error("定时任务异常。SchedulerException！原因为:-->{}", e.getMessage());
        return Result.success();
    }

    @ResponseBody
    @ExceptionHandler(TemplateInputException.class)
    public Result exceptionHandler(TemplateInputException  e){
        log.error("TemplateInputException！原因为:-->{}", e.getMessage());
        e.printStackTrace();
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(TemplateProcessingException.class)
    public Result exceptionHandler(TemplateProcessingException  e){
        log.error("TemplateProcessingException！原因为:-->{}", e.getMessage());
        e.printStackTrace();
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(MessagingException.class)
    public Result exceptionHandler(MessagingException  e){
        log.error("MessagingException！原因为:-->{}", e.getMessage());
        e.printStackTrace();
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(BadSqlGrammarException.class)
    public Result exceptionHandler(BadSqlGrammarException  e){
        log.error("BadSqlGrammarException！原因为:-->{}", e.getSQLException().getMessage());
        e.printStackTrace();
        return Result.fail(500, "服务器内部错误！");
    }

    @ResponseBody
    @ExceptionHandler(value =Exception.class)
    public Result exceptionHandler(Exception e){
        log.error("未知异常！原因是:-->{}",e.getMessage());
        e.printStackTrace();
        return Result.fail(500, "服务器内部错误！");
    }

}
